home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / pgm.m < prev    next >
Encoding:
Text File  |  1992-05-27  |  6.2 KB  |  328 lines

  1. #import <stdio.h>
  2. #import <math.h>
  3. #import <strings.h>
  4. #import <stdlib.h>
  5. #import <streams/streams.h>
  6. #import <appkit/graphics.h>
  7. #import <appkit/NXBitmapImageRep.h>
  8. #import <appkit/color.h>
  9. #import "pgm.h"
  10. #import "NXBitmapImageRepControl.h"
  11. #import "ImageControl.h"
  12.  
  13. @implementation PGM
  14.  
  15.     NXStream        *myStream;
  16.     unsigned char        *data;
  17.     char                type[1000];
  18.     int                width, height, levels;
  19.     int                bits;
  20.     int                cwid;
  21.     int                iwid;
  22.     int                padBits;
  23.  
  24. - init
  25. {
  26.     return self;
  27. }
  28.  
  29. - free
  30. {
  31.     return self;
  32. }
  33.  
  34. - killToEOL
  35. {
  36.     while (NXGetc(myStream) != '\n') ;
  37.     return self;
  38. }
  39.  
  40. - getString: (char *)str from: (NXStream *)stream
  41. {
  42.     char        buffer[256];
  43.     
  44.     do {
  45.         NXScanf(stream, "%s", str);
  46.         if (str[0] == '#') {
  47.             NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
  48.         }
  49.     } while (str[0] == '#');
  50.  
  51.     return self;
  52. }
  53.  
  54. - (int)getIntFrom: (NXStream *)stream
  55. {
  56.     char        buffer[256];
  57.     
  58.     do {
  59.         NXScanf(stream, "%s", buffer);
  60.         if (buffer[0] == '#') {
  61.             NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
  62.         }
  63.         else break;
  64.     } while (1);
  65.     return(atoi(buffer));
  66. }
  67.  
  68. - (BOOL)readRawFromStream
  69. {
  70.     int                x, y, shift, curByte;
  71.     unsigned int        c;
  72.     unsigned int        *dataII = (unsigned int *)data;
  73.  
  74. #ifdef DEBUG
  75.     fprintf(stderr, "Okay, we're off and reading raw data\n");
  76. #endif
  77.  
  78.     [self killToEOL];
  79.  
  80.     shift = 0;
  81.     dataII[curByte = 0] = 0;
  82.     for (x = 0; x < height; x++) {
  83.         for (y = 0; y < width; y++) {
  84.             c = [self getIntFrom: myStream] << (iwid - bits);
  85.             if (NXAtEOS(myStream)) return NO;
  86.             if (shift + bits == iwid) {
  87.                 dataII[curByte++] |= (c >> shift);
  88.                 shift = 0;
  89.                 dataII[curByte] = 0;
  90.             }
  91.             else if (shift + bits > iwid) {
  92.                 dataII[curByte++] |= (c >> shift);
  93.                 shift = shift + bits - iwid;
  94.                 dataII[curByte] = c << (bits - shift);
  95.             }
  96.             else {
  97.                 dataII[curByte] |= (c >> shift);
  98.                 shift += bits;
  99.             }
  100.         }
  101.         shift += padBits;
  102.     }
  103.  
  104.     return YES;
  105. }
  106.  
  107. - (BOOL)readCompressedFromStream
  108. {
  109.     int                x, y, shift, curByte;
  110.     unsigned char        c;
  111.  
  112. #ifdef DEBUG
  113.     fprintf(stderr, "Okay, we're off and reading condensed data\n");
  114. #endif
  115.  
  116.     [self killToEOL];
  117.  
  118.     shift = 0;
  119.     data[curByte = 0] = 0;
  120.     for (x = 0; x < height; x++) {
  121.         for (y = 0; y < width; y++) {
  122.             c = NXGetc(myStream) << cwid - bits;
  123.             if (NXAtEOS(myStream)) return NO;
  124.             if (shift + bits == cwid) {
  125.                 data[curByte++] |= (c >> shift);
  126.                 shift = 0;
  127.                 data[curByte] = 0;
  128.             }
  129.             else if (shift + bits > cwid) {
  130.                 data[curByte++] |= (c >> shift);
  131.                 shift = shift + bits - cwid;
  132.                 data[curByte] = c << (bits - shift);
  133.             }
  134.             else {
  135.                 data[curByte] |= (c >> shift);
  136.                 shift += bits;
  137.             }
  138.         }
  139.         shift += padBits;
  140.     }
  141.  
  142.     return YES;
  143. }
  144.  
  145. - readFromStream: (NXStream *)stream from: sender;
  146. {
  147.     id        image;
  148.  
  149. #ifdef DEBUG
  150.     fprintf(stderr, "Made it to read\n");
  151. #endif
  152.  
  153.     myStream = stream;
  154.  
  155.     [self getString: type from: myStream];
  156.     width = [self getIntFrom: myStream];
  157.     height = [self getIntFrom: myStream];
  158.     levels = [self getIntFrom: myStream];
  159. //    NXScanf(myStream, "%s %d %d %d", type, &width, &height, &levels);
  160.     bits = log(levels + 1) / log (2);
  161.     cwid = sizeof(unsigned char) * 8;
  162.     iwid = sizeof(unsigned int) * 8;
  163. #ifdef DEBUG
  164.     fprintf(stderr, "Type %s of dimensions %dx%d and levels %d or %d bits. intbits = %d, charbits = %d\n", type, width, height, levels + 1, bits, iwid, cwid);
  165. #endif
  166.  
  167.     image = [[NXBitmapImageRep alloc]     initData: NULL
  168.                                         pixelsWide: width
  169.                                         pixelsHigh: height
  170.                                         bitsPerSample: bits
  171.                                         samplesPerPixel: 1
  172.                                         hasAlpha: NO
  173.                                         isPlanar: NO
  174.                                         colorSpace: NX_OneIsWhiteColorSpace
  175.                                         bytesPerRow: 0
  176.                                         bitsPerPixel: 0];
  177.     if (!image) return nil;
  178.     data = [image data]; 
  179.  
  180.     padBits = [image bytesPerRow] * 8 - bits * width;
  181.  
  182.     if (!strcmp(type, "P2")) {
  183.         if (![self readRawFromStream]) {
  184.             [image free];
  185.             return nil;
  186.         }
  187.     }
  188.     else if (!strcmp(type, "P5")) {
  189.         if (![self readCompressedFromStream]) {
  190.             [image free];
  191.             return nil;
  192.         }
  193.     }
  194.     else return nil;
  195.     
  196.     return image;
  197. }
  198.  
  199. static BOOL WriteRaw(id image, NXStream *stream, id imageCon)
  200. {
  201.     int                    w = [image pixelsWide],
  202.                         h = [image pixelsHigh],
  203.                         length = w * h;
  204.     GetPixelNextFunc        myFunc;
  205.     ToGrayFunc            GetColor;
  206.     int                    gray;
  207.     float                    maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
  208.     int                    x, y;
  209.  
  210.     NXPrintf(stream, "P2\n");
  211.     NXPrintf(stream, "%d %d\n", w, h);
  212.     NXPrintf(stream, "%d\n", (int)maxColor);
  213.     [imageCon resetNext];
  214.     myFunc = [imageCon getNextFunction];
  215.     GetColor = [imageCon getToGrayFunction];
  216.     for (x = y = 0; x < length; x++, y++) {
  217.         gray = GetColor(myFunc())->values[0];
  218.         NXPrintf(stream, "%3d ", gray);
  219.         if (y == 16) {
  220.             y = 0;
  221.             NXPrintf(stream, "\n");
  222.         }
  223.     }
  224.  
  225.     return YES;
  226. }
  227.  
  228. static BOOL WriteCompact(id image, NXStream *stream, id imageCon)
  229. {
  230.     int                    w = [image pixelsWide],
  231.                         h = [image pixelsHigh],
  232.                         length = w * h;
  233.     GetPixelNextFunc        myFunc;
  234.     ToGrayFunc            GetGray;
  235.     float                    maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
  236.     int                    x;
  237.  
  238.     NXPrintf(stream, "P5\n");
  239.     NXPrintf(stream, "%d %d\n", w, h);
  240.     NXPrintf(stream, "%d\n", (int)maxColor);
  241.     [imageCon resetNext];
  242.     myFunc = [imageCon getNextFunction];
  243.     GetGray = [imageCon getToGrayFunction];
  244.     for (x = 0; x < length; x++) {
  245.         NXPutc(stream, GetGray(myFunc())->values[0]);
  246.     }
  247.  
  248.     return YES;
  249. }
  250.  
  251. - (BOOL)write: (id)image toStream: (NXStream *)stream from: sender;
  252. {
  253.     id        imageCon = [sender getImageControl: image];
  254.  
  255.     if ([image bitsPerSample] > 8) {
  256.         return WriteRaw(image, stream, imageCon);
  257.     } else {
  258.         return WriteCompact(image, stream, imageCon);
  259.     }
  260. }
  261.  
  262. - readAllFromStream: (NXStream *)stream from: sender
  263. {
  264.     return nil;
  265. }
  266.  
  267. - (BOOL)writeAll: (id)image toStream: (NXStream *)stream
  268. {
  269.     return NO;
  270. }
  271.  
  272. - customSaveView: (int)width
  273. {
  274.     return nil;
  275. }
  276.  
  277. - customOpenView: (int)width
  278. {
  279.     return nil;
  280. }
  281.  
  282. - (char *)getFormatName
  283. {
  284.     return("Portable Graymap (PGM)");
  285. }
  286.  
  287.  - (BOOL)setCustomParameter: (const char *)parameter withValue: (void *)ptr
  288. {
  289.     return NO;
  290. }
  291.  
  292.  - (void *)getCustomParameter: (const char *)parameter
  293. {
  294.     return nil;
  295. }
  296.  
  297. - (char *)copyrightNotice
  298. {
  299.     return "PGM Converter\nby Alex Raftis\nCopyright (c) 1991 Cal Poly State University\nEmail bugs to alex@data.ACS.CalPoly.EDU";
  300. }
  301.  
  302. - (int)errorState
  303. {
  304.     return CONVERT_ERR_NONE;
  305. }
  306.  
  307. - (int)errorMessage
  308. {
  309.     return ERROR_NO_ERROR;
  310. }
  311.  
  312. - (char *)errorStringMessage
  313. {
  314.     return NULL;
  315. }
  316.  
  317. - (BOOL)needsWindowServer;
  318. {
  319.     return NO;
  320. }
  321.  
  322. - (char *)protocolVersion
  323. {
  324.     return "1.0";
  325. }
  326.  
  327. @end
  328.